/** 抽象类是一种无法被实例化的类，专门来定义类的结构和行为，类种可以写抽象方法，
 *  也可以写具体实现，抽象类主要用来为其派生类提供一个基础结构，要求其派生类必须实现其中的
 *  抽象方法。
 *  简记：抽象类不能实例化，其意义是可以被继承，抽象类里可以有普通方法，也可以有抽象方法
 * 
*/

abstract class Package {
    // 构造方法
    constructor(public weight: number) { }
    // 抽象方法
    abstract calculate(): number
    // 具体方法
    printPackage() {
        console.log(`包裹重量为:${this.weight}kg,运费为${this.calculate()}元`)
    }
}
// 抽象类 不能被new 可以被继承

class StandardPackage extends Package {
    constructor(
        weight: number,
        public unitPrice: number) { super(weight) }
    calculate(): number {
        return this.weight * this.unitPrice
    }
}

const s1 = new StandardPackage(10, 5)
console.log(s1.calculate())
s1.printPackage()


class ExpressPackage extends Package {
    constructor(
        weight: number,
        public unitPrice: number,
        public additional: number) { super(weight) }
    calculate(): number {
        if (this.weight > 10) {
            return 10 * this.unitPrice + (this.weight - 10) * this.additional
        } else {
            return this.weight * this.unitPrice
        }
    }

}

const e1 = new ExpressPackage(13,8,2)
e1.printPackage()
/**
 * 总结
 * 1.定义通用接口：为一组相关的类定义通用的行为（方法或属性）时。
 * 2.提供基础实现：在抽象类中提供某些方法或为其提供基础实现，这样派生类就可以继承这些实现。
 * 3.确保关键实现：强制派生类实现一些关键行为。
 * 4.共享代码和逻辑：当多个类需要共享部分代码时，抽象类可以避免代码重复。
 * 
 */
